﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Input;
using System.Windows.Navigation;

using System.Windows;
using System.Windows.Data;
using System.Windows.Documents;

namespace D3crft.Windows.Effects {
    class ecShadowBlurQueue {

        Grid oRootGrid;
        BlurEffect oBlur;
        UserControl oShadow;

        DispatcherTimer oTimer;

        int iQueueDepth = 0;
        bool bTimerMode = true;
        int iEffectTimeMS = 150;
        int iSteps = 6;
        double dBlurSteps = 0.8;
        double dOpacitySteps = 0.04;

        double dMaxBlurRadius = 4.8;
        double dMaxOpacity = 0.24;

        public ecShadowBlurQueue(Grid _oRootGrid) {
            oRootGrid = _oRootGrid;
            oTimer = new DispatcherTimer();
            oTimer.Interval = TimeSpan.FromMilliseconds(25.0);
            oTimer.Tick += new EventHandler(ev_oTimer_Tick);
        }

        public double Interval {
            get { return oTimer.Interval.Milliseconds; }
            set {
                oTimer.Interval = TimeSpan.FromMilliseconds(value);
                iSteps = iEffectTimeMS / (int)oTimer.Interval.Milliseconds;
                dBlurSteps = dMaxBlurRadius / (double)iSteps;
                dOpacitySteps = dMaxOpacity / (double)iSteps;
            }
        }

        public int EffectTimeMS {
            get { return iEffectTimeMS; }
            set {
                iEffectTimeMS = value;
                iSteps = iEffectTimeMS / (int)oTimer.Interval.Milliseconds;
                dBlurSteps = dMaxBlurRadius / (double)iSteps;
                dOpacitySteps = dMaxOpacity / (double)iSteps;
            }
        }

        public double MaxBlurRadius {
            get { return dMaxBlurRadius; }
            set {
                dMaxBlurRadius = value;
                dBlurSteps = dMaxBlurRadius / (double)iSteps;
            }
        }

        public double MaxOpacity {
            get { return dMaxBlurRadius; }
            set {
                dMaxOpacity = value;
                dOpacitySteps = dMaxOpacity / (double)iSteps;
            }
        }


        public void Queue(int iQueue) {
            if (iQueueDepth == 0) {
                if (iQueue > 0) {
                    // enable
                    do_EnableEffect();
                }
                else {
                    // disable
                    do_DisableEffect();
                }
            }
            else if (iQueueDepth == 1) {
                if (iQueue < 0) {
                    // disable
                    do_DisableEffect();
                }
            }

            iQueueDepth += iQueue;
            if (iQueueDepth < 0) iQueueDepth = 0;
        }



        private void do_EnableEffect() {
            oBlur = new BlurEffect();
            oBlur.Radius = 0.0;
            oRootGrid.Effect = oBlur;

            oShadow = new UserControl();
            oShadow.Background = Brushes.Black;
            oShadow.Opacity = 0.0;
            oShadow.Margin = new Thickness(-10.0, -10.0, -10.0, -10.0);
            oRootGrid.Children.Add(oShadow);

            bTimerMode = true;
            oTimer.Start();
        }

        private void do_DisableEffect() {
            oBlur.Radius = dMaxBlurRadius;
            oShadow.Opacity = dMaxOpacity;
            bTimerMode = false;
            oTimer.Start();
        }

        private void ev_oTimer_Tick(object sender, EventArgs ea) {
            if (bTimerMode) {
                oBlur.Radius += dBlurSteps;
                oShadow.Opacity += dOpacitySteps;
                if (oBlur.Radius >= dMaxBlurRadius) {
                    oTimer.Stop();
                }
            }
            else {
                oBlur.Radius -= dBlurSteps;
                oShadow.Opacity -= dOpacitySteps;
                if (oBlur.Radius <= 0.0) {
                    oTimer.Stop();
                    oRootGrid.Children.Remove(oShadow);
                    oRootGrid.Effect = null;
                }
            }
        }

    }
}
